using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using AbstraX.Contracts;
using MvvmTreeView;
using System.Windows;
using System.Windows.Controls;
using System.Diagnostics;
#if SILVERLIGHT
using AbstraX.ClientInterfaces;
using Hydra.Shell.Enumerations;
using Hydra.Shell.Interfaces;
using Hydra.Shell.Implementations;
using Hydra.Shell.Attributes;
using Hydra.Shell.Constants;
using Hydra.Shell;
using Hydra.PackageFramework;
using System.ServiceModel.DomainServices.Client;


#else
using AbstraX.ServerInterfaces;
#endif
using AbstraX;
using EntityProvider.Web;
using NodeExpander;
using Utils;

#if !SILVERLIGHT
public interface IAbstraXDocumentSave { }
#endif

#if SILVERLIGHT
namespace EntityProvider.Web.Entities.Client
{
    public interface IEntityProviderExtension : IAbstraXExtension
    {

    }
       
    public class EntityProviderExtension : IEntityProviderExtension 
    {
        private IBase baseObject;
        private ITreeNode treeNode;
        private ContextMenu contextMenu;
        private ContextMenu commentMenu;
        private INodeExpander nodeExpander;
        private uint docCookie;
        private bool loading;
        private bool isDirty;
        private List<IDocumentView> views;
        private IQueryServiceProvider serviceProvider;
        private EntityProviderClientService clientService;
        public EventHandler Disposed { get; set; }
        
        
    
        public void Initialize(IBase baseObject, ITreeNode treeNode) 
        {
            this.baseObject = baseObject;            
            this.treeNode = treeNode;
            this.nodeExpander = treeNode.NodeExpander;
            clientService = new EntityProviderClientService();
            views = new List<IDocumentView>();
        }

        public void Initialize(IBase baseObject)
        {
            this.baseObject = baseObject;
            clientService = new EntityProviderClientService();
            views = new List<IDocumentView>();
        }






        public IBase BaseObject
        {
            get 
            {
                return baseObject; 

            }
        }

        public enum Multiplicity : int
        {           
            OneToOne = 1,
            OneToMany,
            OneToZeroOrOne,
            ManyToOne,
            ManyToMany,
            ManyToZeroOrOne,
            ZeroOrOneToOne,
            ZeroOrOneToMany,
            Undefined,

        }

        public bool DoesAllowRename(IBase baseObject, ITreeNode treeNode)
        {
            return true;
        }

#region EntityContainer
        private void AddNewEntityContainer(object sender, RoutedEventArgs r)
        {
            var editNode = treeNode.AddEditNode(0, "New EntityContainer");

            editNode.AfterLabelEdit += (sender2, e2) =>
            {
                // this should be AddNewEntity with the following parameters:
                //  (IBase baseObject, ITreeNode parentTreeNode, string nodeText)

                var invokeOperation = clientService.AddNewEntityContainer(baseObject, e2.Label);

                invokeOperation.Completed += (sender3, e3) =>
                {
                    Guid newID;

                    if (invokeOperation.HasError)
                    {
                        throw invokeOperation.Error;
                    }
                    else if (!Guid.TryParse((string)invokeOperation.Value, out newID))
                    {
                        throw new Exception("Operation expects return value to be in proper format.");
                    }
                    else
                    {
                        treeNode.Parent.LoadChildren();
                    }
                };
            };
        }

        private void RenameEntityContainer(object sender, RoutedEventArgs r)
        {
            treeNode.BeginEdit();
            
            treeNode.AfterLabelEdit += (sender2, e2) =>
            {
                var invokeOperation = clientService.RenameEntityContainer(baseObject, e2.Label);

                invokeOperation.Completed += (sender3, e3) =>
                {
                    Guid newID;

                    if (invokeOperation.HasError)
                    {
                        throw invokeOperation.Error;
                    }
                    else if (!Guid.TryParse((string) invokeOperation.Value, out newID))
                    {
                        throw new Exception("Operation expects return value to be in proper format.");
                    }
                    else
                    {
                        treeNode.Parent.LoadChildren();
                    }
                };
            };
        }

        private void DeleteEntityContainer(object sender, RoutedEventArgs r)
        {
            if (treeNode.HasChildren == true)
            {
                MessageBox.Show("Cannot delete nodes with children.");
            }
            else
            {
                if (MessageBox.Show(string.Format("Are you sure you want to delete \"{0}\"?", treeNode.Text), "Delete?", MessageBoxButton.OKCancel) == System.Windows.MessageBoxResult.OK)
                {
                    var invokeOperation = clientService.DeleteEntityContainer(baseObject);

                    invokeOperation.Completed += (sender2, e2) =>
                    {
                        Guid newID;

                        if (invokeOperation.HasError)
                        {
                            throw invokeOperation.Error;
                        }
                        else if (!Guid.TryParse((string)invokeOperation.Value, out newID))
                        {
                            throw new Exception("Operation expects return value to be in proper format.");
                        }
                        else
                        {
                            treeNode.Parent.LoadChildren();
                        }
                    };
                }
            }
        }
#endregion

#region EntitySet
        private void AddNewEntitySet(object sender, RoutedEventArgs r)
        {
            var editNode = treeNode.AddEditNode(0, "New EntitySet");

            editNode.AfterLabelEdit += (sender2, e2) =>
            {
                var invokeOperation = clientService.AddNewEntitySet(baseObject, e2.Label);

                invokeOperation.Completed += (sender3, e3) =>
                {
                    Guid newID;

                    if (invokeOperation.HasError)
                    {
                        throw invokeOperation.Error;
                    }
                    else if (!Guid.TryParse((string) invokeOperation.Value, out newID))
                    {
                        throw new Exception("Operation expects return value to be in proper format.");
                    }
                    else
                    {
                        treeNode.LoadChildren();
                    }
                };
            };
        }

        private void RenameEntitySet(object sender, RoutedEventArgs r)
        {
            
            string oldName = baseObject.Name.ToString();
            treeNode.BeginEdit();
            
            treeNode.AfterLabelEdit += (sender2, e2) =>
            {
                var invokeOperation = clientService.RenameEntitySet(baseObject, e2.Label, oldName);

                invokeOperation.Completed += (sender3, e3) =>
                {
                  
                    if (invokeOperation.HasError)
                    {
                        throw invokeOperation.Error;
                    }                    
                    else
                    {
                        //treeNode.Text = invokeOperation.Value[0];
                        //treeNode.Parent.Text = invokeOperation.Value[1];
                        treeNode.Parent.LoadChildren();
                    }
                };
            };
        }
 
#endregion

#region EntityType
        private void AddNewEntityType(object sender, RoutedEventArgs r)
        {
            var editNode = treeNode.AddEditNode(0, "New EntityType");

            editNode.AfterLabelEdit += (sender2, e2) =>
            {
                var invokeOperation = clientService.AddNewEntityType(baseObject, e2.Label);

                invokeOperation.Completed += (sender3, e3) =>
                {
                    Guid newID;

                    if (invokeOperation.HasError)
                    {
                        throw invokeOperation.Error;
                    }
                    else if (!Guid.TryParse((string) invokeOperation.Value, out newID))
                    {
                        throw new Exception("Operation expects return value to be in proper format.");
                    }
                    else
                    {
                        treeNode.LoadChildren();
                    }
                };
            };
        }

        private void RenameEntityType(object sender, RoutedEventArgs r)
        {
            
            string oldName = baseObject.Name.ToString();
            treeNode.BeginEdit();
            
            treeNode.AfterLabelEdit += (sender2, e2) =>
            {
                var invokeOperation = clientService.RenameEntityType(baseObject, e2.Label, oldName);

                invokeOperation.Completed += (sender3, e3) =>
                {
                  
                    if (invokeOperation.HasError)
                    {
                        throw invokeOperation.Error;
                    }                    
                    else
                    {
                        //treeNode.Text = invokeOperation.Value[0];
                        //treeNode.Parent.Text = invokeOperation.Value[1];
                        treeNode.Parent.LoadChildren();
                    }
                };
            };
        }

        private void DeleteEntityType(object sender, RoutedEventArgs r)
        {
            if (treeNode.HasChildren == true)
            {
                MessageBox.Show("Cannot delete nodes with children.");
            }
            else
            {
                if (MessageBox.Show(string.Format("Are you sure you want to delete \"{0}\"?", treeNode.Text), "Delete?", MessageBoxButton.OKCancel) == System.Windows.MessageBoxResult.OK)
                {
                    var invokeOperation = clientService.DeleteEntityType(baseObject, treeNode.Text);

                    invokeOperation.Completed += (sender2, e2) =>
                    {                        

                        if (invokeOperation.HasError)
                        {
                            throw invokeOperation.Error;
                        }                        
                        else
                        {
                            treeNode.Remove();
                            treeNode.Parent.LoadChildren();
                        }
                    };
                }
            }
        }
#endregion

#region Property
        private void AddNewProperty(object sender, RoutedEventArgs r)
        {
            var editNode = treeNode.AddEditNode(0, "New Property");

            editNode.AfterLabelEdit += (sender2, e2) =>
            {
                var invokeOperation = clientService.AddNewProperty(baseObject, e2.Label);

                invokeOperation.Completed += (sender3, e3) =>
                {
                    Guid newID;

                    if (invokeOperation.HasError)
                    {
                        throw invokeOperation.Error;
                    }
                    else if (!Guid.TryParse((string) invokeOperation.Value, out newID))
                    {
                        throw new Exception("Operation expects return value to be in proper format.");
                    }
                    else
                    {
                        treeNode.LoadChildren();
                    }
                };
            };
        }

        private void RenameProperty(object sender, RoutedEventArgs r)
        {
            string oldName = baseObject.Name.ToString();
            treeNode.BeginEdit();
            
            treeNode.AfterLabelEdit += (sender2, e2) =>
            {
                var invokeOperation = clientService.RenameProperty(baseObject, e2.Label, oldName);

                invokeOperation.Completed += (sender3, e3) =>
                {
                    if (invokeOperation.HasError)
                    {
                        throw invokeOperation.Error;
                    }                    
                    {
                        treeNode.Parent.LoadChildren();
                    }
                };
            };
        }

        private void DeleteProperty(object sender, RoutedEventArgs r)
        {
            if (treeNode.HasChildren == true)
            {
                MessageBox.Show("Cannot delete nodes with children.");
            }
            else
            {
                if (MessageBox.Show(string.Format("Are you sure you want to delete \"{0}\"?", treeNode.Text), "Delete?", MessageBoxButton.OKCancel) == System.Windows.MessageBoxResult.OK)
                {
                    var invokeOperation = clientService.DeleteProperty(baseObject, treeNode.Text);

                    invokeOperation.Completed += (sender2, e2) =>
                    {
                        
                        if (invokeOperation.HasError)
                        {
                            throw invokeOperation.Error;
                        }                        
                        else
                        {
                            treeNode.Remove();
                            treeNode.Parent.LoadChildren();
                        }
                    };
                }
            }
        }

        private void ExpandPropertyMenu(object sender, RoutedEventArgs r)
        {
        #region Menu Stubs
            // Child Window
            ChildWindow cwExpProperty = new ChildWindow()
            {
                Height = 300,
                Width = 350,
            };

            // Grid Definitions
            Grid gridExpander = new Grid();

            ColumnDefinition cd1 = new ColumnDefinition();
            cd1.Width = new GridLength(150);

            ColumnDefinition cd2 = new ColumnDefinition();
            cd2.Width = new GridLength(150);

            gridExpander.ColumnDefinitions.Add(cd1);
            gridExpander.ColumnDefinitions.Add(cd2);

            StackPanel spLabels = new StackPanel();
            StackPanel spInputs = new StackPanel();

            gridExpander.Children.Add(spLabels);
            gridExpander.Children.Add(spInputs);

            spLabels.SetValue(Grid.ColumnProperty, 0);
            spInputs.SetValue(Grid.ColumnProperty, 1);


            // TextBlock Labels
            TextBlock lblDataType = new TextBlock()
            {
                Height = 25,
                Width = 150,
                Text = "Data Type",
            };

            TextBlock lblAllowNull = new TextBlock()
            {
                Height = 25,
                Width = 150,
                Text = "Allow Null",
            };

            TextBlock lblDefaultValue = new TextBlock()
            {
                Height = 25,
                Width = 150,
                Text = "Default Value",
            };

            TextBlock lblDataSize = new TextBlock()
            {
                Height = 25,
                Width = 150,
                Text = "Data Size",
            };

            TextBlock lblKey= new TextBlock()
            {
                Height = 25,
                Width = 150,
                Text = "Key",
            };


            // ComboBox Data Type
            ComboBox cmbDataType = new ComboBox()
            {
                Height = 25,
                Width = 150,
            };

            ComboBoxItem cmbTypeBoolean = new ComboBoxItem()
            {
                Name = "Boolean",
                Content = "Boolean",
            };

            ComboBoxItem cmbTypeSByte = new ComboBoxItem()
            {
                Name = "SByte",
                Content = "SByte",
            };

            ComboBoxItem cmbTypeByte = new ComboBoxItem()
            {
                Name = "Byte",
                Content = "Byte",
            };

            ComboBoxItem cmbTypeInt16 = new ComboBoxItem()
            {
                Name = "Int16",
                Content = "Int16",
            };

            ComboBoxItem cmbTypeInt32 = new ComboBoxItem()
            {
                Name = "Int32",
                Content = "Int32",
            };

            ComboBoxItem cmbTypeInt64 = new ComboBoxItem()
            {
                Name = "Int64",
                Content = "Int64",
            };

            ComboBoxItem cmbTypeSingle = new ComboBoxItem()
            {
                Name = "Single",
                Content = "Single",
            };

            ComboBoxItem cmbTypeDouble = new ComboBoxItem()
            {
                Name = "Double",
                Content = "Double",
            };

            ComboBoxItem cmbTypeDecimal = new ComboBoxItem()
            {
                Name = "Decimal",
                Content = "Decimal",
            };

            ComboBoxItem cmbTypeDateTime = new ComboBoxItem()
            {
                Name = "DateTime",
                Content = "DateTime",
            };

            ComboBoxItem cmbTypeTime = new ComboBoxItem()
            {
                Name = "Time",
                Content = "Time",
            };

            ComboBoxItem cmbTypeString = new ComboBoxItem()
            {
                Name = "String",
                Content = "String",
            };

            ComboBoxItem cmbTypeBinary = new ComboBoxItem()
            {
                Name = "Binary",
                Content = "Binary",

            };

            cmbDataType.Items.Add(cmbTypeBinary);
            cmbDataType.Items.Add(cmbTypeBoolean);
            cmbDataType.Items.Add(cmbTypeByte);
            cmbDataType.Items.Add(cmbTypeDateTime);
            cmbDataType.Items.Add(cmbTypeDecimal);
            cmbDataType.Items.Add(cmbTypeDouble);
            cmbDataType.Items.Add(cmbTypeInt16);
            cmbDataType.Items.Add(cmbTypeInt32);
            cmbDataType.Items.Add(cmbTypeInt64);
            cmbDataType.Items.Add(cmbTypeSByte);
            cmbDataType.Items.Add(cmbTypeSingle);
            cmbDataType.Items.Add(cmbTypeString);
            cmbDataType.Items.Add(cmbTypeTime);

            // TextBox Default Value
            TextBox txtDefaultValue= new TextBox()
            {
                Height = 25,
                Width = 150,
            };

            // TextBox Data Size
            TextBox txtDataSize = new TextBox()
            {
                Height = 25,
                Width = 150,
            };

            /*
            txtDataSize.TextChanged += (sender2, e2) =>
            {
                if (System.Text.RegularExpressions.Regex.IsMatch("[^0-9]", txtDataSize.Text))
                {
                    MessageBox.Show("Numbers Only");
                    txtDataSize.Text.Remove(txtDataSize.Text.Length, 1);
                }
            };
            */

            // ComboBox Allow Null
            ComboBox cmbAllowNull = new ComboBox()
            {
                Height = 25,
                Width = 150,
            };

            ComboBoxItem cmbNullTrue = new ComboBoxItem()
            {
                Name = "True",
                Content = "True",
            };

            ComboBoxItem cmbNullFalse = new ComboBoxItem()
            {
                Name = "False",
                Content = "False ",
            };

            cmbAllowNull.Items.Add(cmbNullTrue);
            cmbAllowNull.Items.Add(cmbNullFalse);


            // ComboBox Key Status
            ComboBox cmbKey = new ComboBox()
            {
                Height = 25,
                Width = 150,
            };

            ComboBoxItem cmbKeyPrimary = new ComboBoxItem()
            {
                Name = "PrimaryKey",
                Content = "Primary Key",
            };

            ComboBoxItem cmbKeyForeign = new ComboBoxItem()
            {
                Name = "ForeignKey",
                Content = "Foreign Key",
            };

            ComboBoxItem cmbKeyNone = new ComboBoxItem()
            {
                Name = "None",
                Content = "None",
            };

            cmbKey.Items.Add(cmbKeyPrimary);
            cmbKey.Items.Add(cmbKeyForeign);
            cmbKey.Items.Add(cmbKeyNone);


            // Submit Button
            Button btnSubmitProperties = new Button()
            {
                Height = 25,
                Width = 150,
                Content = "Submit",
            };

            btnSubmitProperties.Click += (sender2, e2) =>
            {
                var dataType = cmbDataType.SelectionBoxItem.ToString();
                var allowNull = cmbAllowNull.SelectionBoxItem.ToString();
                var defaultValue = txtDefaultValue.Text;
                var dataSize = txtDataSize.Text;
                var keyStatus = cmbKey.SelectionBoxItem.ToString();

                ExpandProperty(baseObject, dataType, allowNull, defaultValue, dataSize, keyStatus);
            };

            // Add Elements to Grid
            spLabels.Children.Add(lblDataType);
            spLabels.Children.Add(lblAllowNull);
            spLabels.Children.Add(lblDefaultValue);
            spLabels.Children.Add(lblDataSize);
            spLabels.Children.Add(lblKey);

            spInputs.Children.Add(cmbDataType);
            spInputs.Children.Add(cmbAllowNull);
            spInputs.Children.Add(txtDefaultValue);
            spInputs.Children.Add(txtDataSize);
            spInputs.Children.Add(cmbKey);

            spInputs.Children.Add(btnSubmitProperties);
            
            cwExpProperty.Content = gridExpander;

            // Display Window
            cwExpProperty.Show();
            #endregion
        }

        private void ExpandProperty(IBase baseObject, string dataType, string allowNull, string defaultValue, string dataSize, string keyStatus)
        {
            var invokeOperation = clientService.ExpandProperty(baseObject, dataType, allowNull, defaultValue, dataSize, keyStatus);

            invokeOperation.Completed += (sender2, e2) =>
            {
                Guid newID;

                if (invokeOperation.HasError)
                {
                    throw invokeOperation.Error;
                }
                else if (!Guid.TryParse((string)invokeOperation.Value, out newID))
                {
                    throw new Exception("Operation expects return value to be in proper format.");
                }
                else
                {
                    treeNode.Parent.LoadChildren();
                }
            };
        }



#endregion

#region NavigationProperty
        private void AddNewNavigationProperty(object sender, RoutedEventArgs r)
        {
      /*       var editNode = treeNode.AddEditNode(0, "New NavigationProperty");

       //    editNode.AfterLabelEdit += (sender2, e2) =>
        //    {
        //        var invokeOperation = clientService.AddNewNavigationProperty(baseObject, e2.Label);

                invokeOperation.Completed += (sender3, e3) =>
                {
                    Guid newID;

                    if (invokeOperation.HasError)
                    {
                        throw invokeOperation.Error;
                    }
                    else if (!Guid.TryParse((string) invokeOperation.Value, out newID))
                    {
                        throw new Exception("Operation expects return value to be in proper format.");
                    }
                    else
                    {
                        treeNode.LoadChildren();
                    }
                };
            };*/
        }

        private void RenameNavigationProperty(object sender, RoutedEventArgs r)
        {
      /*      //treeNode.BeginEdit();
            
            //treeNode.AfterLabelEdit += (sender2, e2) =>
            //{
            //    var invokeOperation = clientService.RenameNavigationProperty(baseObject, e2.Label);

                invokeOperation.Completed += (sender3, e3) =>
                {
                    Guid newID;

                    if (invokeOperation.HasError)
                    {
                        throw invokeOperation.Error;
                    }
                    else if (!Guid.TryParse((string) invokeOperation.Value, out newID))
                    {
                        throw new Exception("Operation expects return value to be in proper format.");
                    }
                    else
                    {
                        treeNode.Parent.LoadChildren();
                    }
                };
            };  */
        }

        private void DeleteNavigationProperty(object sender, RoutedEventArgs r)
        {
   /*         var invokeOperation = clientService.DeleteNavigationProperty(baseObject);

            invokeOperation.Completed += (sender2, e2) =>
            {
                Guid newID;

                if (invokeOperation.HasError)
                {
                    throw invokeOperation.Error;
                }
                else if (!Guid.TryParse((string) invokeOperation.Value, out newID))
                {
                    throw new Exception("Operation expects return value to be in proper format.");
                }
                else
                {
                    treeNode.Parent.LoadChildren();
                }
            }; */
        }

        private void SelectMultiplicity(object sender, RoutedEventArgs r)
        {
    /*        var invokeOperation = clientService.SelectMultiplicity(baseObject);


                if (invokeOperation.HasError)
                {
                    throw invokeOperation.Error;
                }
                else if (!Guid.TryParse((string) invokeOperation.Value, out newID))
                {
                    throw new Exception("Operation expects return value to be in proper format.");
                }
                else
                {
                    treeNode.Parent.LoadChildren();
                }
            }; */
        }
#endregion

#region Comments
        private List<IContextMenuItem> GetCommentMenuItems(IBase baseObject)
        {
            if (baseObject.HasDocumentation == true)
            {
                commentMenu = new ContextMenu
                {
                    Items = new List<IContextMenuItem>()
                    {
                        new ContextMenuItem(null, null,"View Comments", null, ViewComments),
                        new ContextMenuItem(null, null,"Edit Comments", null, EditComments),
                        new ContextMenuItem(null, null,"Delete Comments", null, DeleteComments),

                    }
                };
            }
            else if (baseObject.HasDocumentation == false)
            {
                commentMenu = new ContextMenu
                {
                    Items = new List<IContextMenuItem>()
                    {
                        new ContextMenuItem(null, null,"Add Comments", null, AddComments),
                    }
                };
            }

            return commentMenu.Items;
        }

      public void ViewComments(object sender, RoutedEventArgs r)
        {


            DoDefaultCommand();

            
            
          var invokeOperation = clientService.ViewComments(baseObject);

            invokeOperation.Completed += (sender2, e2) =>
            {
                Guid newID;

                if (invokeOperation.HasError)
                {
                    throw invokeOperation.Error;
                }
                //else if (!Guid.TryParse((string) invokeOperation.Value, out newID))
                //{
                //    throw new Exception("Operation expects return value to be in proper format.");
                //}
                else
                {
                    treeNode.Parent.LoadChildren();
                }
            }; 
        }

        private void AddComments(object sender, RoutedEventArgs r)
        {
            string documentationSummary = "new entity set commentsummary";//baseObject.DocumentationSummary;
            string documentation = "new entity set comment";// baseObject.Documentation;

            DoDefaultCommand();

            var invokeOperation = clientService.AddComments(baseObject, documentationSummary, documentation);

            invokeOperation.Completed += (sender2, e2) =>
            {
                Guid newID;

                if (invokeOperation.HasError)
                {
                    throw invokeOperation.Error;
                }
                else if (!Guid.TryParse((string)invokeOperation.Value, out newID))
                {
                    throw new Exception("Operation expects return value to be in proper format.");
                }
                else
                {
                    treeNode.Parent.LoadChildren();
                }
            };
        }

        private void EditComments(object sender, RoutedEventArgs r)
        {
            var invokeOperation = clientService.EditComments(baseObject);

            invokeOperation.Completed += (sender2, e2) =>
            {
                Guid newID;

                if (invokeOperation.HasError)
                {
                    throw invokeOperation.Error;
                }
                //else if (!Guid.TryParse((string)invokeOperation.Value, out newID))
                //{
                //    throw new Exception("Operation expects return value to be in proper format.");
                //}
                else
                {
                    treeNode.Parent.LoadChildren();
                }
            };
        }


        private void DeleteComments(object sender, RoutedEventArgs r)
        {
            var invokeOperation = clientService.checkForCommentstoDelete(baseObject);


            invokeOperation.Completed += (sender2, e2) =>
            {

                if (invokeOperation.HasError)
                {
                    throw invokeOperation.Error;
                }
                //else
                //{
                //    if(invokeOperation.Value = true)
                //    {
                //    MessageBox.Show("Comment not there.");
                //    }
                //    else
                //    {
                //        (MessageBox.Show(string.Format("Are you sure you want to delete \"{0}\"?"), "Delete?", MessageBoxButton.OKCancel) == System.Windows.MessageBoxResult.OK)

                //       // var invokeOperation1 = clientService.DeleteComments(invokeOperation);

                //        //if(invokeOperation1 = true.Equals())
                //        //{
                //        //}
                //    }

            };
        }

           
#endregion

#region Keyboard Commands

        public string KeyFauxArrowRight()
        {
            return "Success";
        }

        public string KeyFauxArrowLeft()
        {
            return "Success";
        }

        public string KeyShiftNAddNew()
        {
            return "Success";
        }

        public string KeyF2Rename()
        {
            return "Success";
        }

        public string KeyDelDelete()
        {
            return "Success";
        }
#endregion

        private void DoDefaultCommand()
        {
            // TODO - call this method to load the document, i.e. "View Comments..."

            var commands = new CommandSet<HydraUIHierarchyWindowCmdIds>();
            var doubleClickCmdInfo = commands[(uint)HydraUIHierarchyWindowCmdIds.DoubleClick];
            var commandTarget = (ICommandTarget)treeNode;

            doubleClickCmdInfo.QueryCommandStatus = false;

            if (commandTarget.GetCommands<HydraUIHierarchyWindowCmdIds>(commands))
            {
                if (doubleClickCmdInfo.Command != null && doubleClickCmdInfo.Command.CanExecute(treeNode))
                {
                    doubleClickCmdInfo.Command.Execute(treeNode);
                }
            }
        }

        public ContextMenu ContextMenu
        {    
            get
            {
                if (contextMenu == null)
                {
                    var commentMenuItems = GetCommentMenuItems(baseObject);

                    switch (baseObject.GetType().Name)
                    {
                        case "Entity_Container":
        
                            contextMenu = new ContextMenu
                            {
                                Items = new List<IContextMenuItem>()
                                {
                                    new ContextMenuItem(null, null,"Rename EntityContainer", null, RenameEntityContainer),
                                    new ContextMenuItem(null, null,"Delete EntityContainer", null, DeleteEntityContainer),
                                    
                                    // Add New EntityType will create an EntitySet node first, then an EntityType node.
                                    new ContextMenuItem(null, null,"Add New EntityType (and EntitySet)", null, AddNewEntitySet),
                                }
                            };
                            contextMenu.Items.AddRange(commentMenuItems);
                            break;

                        case "Entity_Set":
                            contextMenu = new ContextMenu
                            {
                                Items = new List<IContextMenuItem>()
                                {
                                    new ContextMenuItem(null, null,"Rename EntitySet", null, RenameEntitySet),
                                }
                            };
                            contextMenu.Items.AddRange(commentMenuItems);
                            break;

                        case "EntityType":
        
                            contextMenu = new ContextMenu
                            {
                                Items = new List<IContextMenuItem>()
                                {
                                    
                                    new ContextMenuItem(null, null,"Rename EntityType", null, RenameEntityType),
                                    new ContextMenuItem(null, null,"Delete Entity Type", null, DeleteEntityType),

                                    new ContextMenuItem(null, null,"Add New Property", null, AddNewProperty),

                                    new ContextMenuItem(null, null,"Add New NavigationProperty", null, AddNewNavigationProperty),

                                    //new ContextMenuItem(null, null,"Add Related EntityType", null, AddRelatedEntityType),
                                    //new ContextMenuItem(null, null,"Remove Related EntityType", null, RemoveRelatedEntityType),
                                }
                            };
                            contextMenu.Items.AddRange(commentMenuItems);
                            break;

                        case "EntityProperty":
                            contextMenu = new ContextMenu
                            {
                                Items = new List<IContextMenuItem>()
                                {
                                    new ContextMenuItem(null, null,"Rename Property", null, RenameProperty),
                                    new ContextMenuItem(null, null,"Delete Property", null, DeleteProperty),
                                    new ContextMenuItem(null, null,"Expand Property (Menu)", null, ExpandPropertyMenu),
                                }
                            };
                            contextMenu.Items.AddRange(commentMenuItems);
                            break;

                        case "NavigationProperty":
                            contextMenu = new ContextMenu
                            {
                                Items = new List<IContextMenuItem>()
                                {   
                                    new ContextMenuItem(null, null,"Rename NavigationProperty", null, RenameNavigationProperty),
                                    new ContextMenuItem(null, null,"SelectMultiplicity", null, SelectMultiplicity),
                                }
                            };
                            contextMenu.Items.AddRange(commentMenuItems);
                            break;

                        default:
                            contextMenu = null;
                            break;
                    }
                }
            return contextMenu;
            }
        }

        public INodeExpander NodeExpander
        {
            get
            {
                if (nodeExpander == null)
                {
                    switch (baseObject.GetType().Name)
                    {
                        case "EntityProperty":
                            nodeExpander.ExpanderControl = new ExpanderControl
                            {
                                Slots = new List<IExpanderSlot>()
                                {
                                    new ExpanderSlot(1,"Allow Null", true, true, null, null, null, null),
                                    new ExpanderSlot(2,"Data Size", true, true, null, null, null, null),
                                    new ExpanderSlot(3,"Data Type", true, true, null, null, null, null),
                                    new ExpanderSlot(4,"Default Value", true, true, null, null, null, null),
                                    new ExpanderSlot(5,"Key Field", true, true, null, null, null, null),
                                }
                            };
                            break;

                        default:
                            nodeExpander = null;
                            break;
                    }
                }
                return nodeExpander;
            }
        }

        // TODO - implement all these, implement gets by getting directly from baseObject, implement sets by setting to module level variables until Save is called.

        string IAbstraXDocumentSave.ID
        {
            get
            {
                return baseObject.ID;
            }
            set
            {
                // not settable

                throw new NotImplementedException();
            }
        }

        string IAbstraXDocumentSave.Name
        {
            get
            {
                return baseObject.Name;
            }
            set
            {
                // not settable

                throw new NotImplementedException();
            }
        }

        string IAbstraXDocumentSave.DesignComments
        {
            get
            {
                return baseObject.DesignComments;
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        string IAbstraXDocumentSave.Documentation
        {
            get
            {
                return baseObject.Documentation;
            }
            set
            {
                throw new NotImplementedException();
                //var invokeOperation = clientService.ViewComments(baseObject);

                //var documentation = invokeOperation.ToString();
            }
        }

        string IAbstraXDocumentSave.DocumentationSummary
        {
            get
            {
                return baseObject.DocumentationSummary;
            }
            set
            {
                throw new NotImplementedException();
                //var invokeOperation = clientService.ViewComments(baseObject);

                //var documentationSummary = invokeOperation.ToString();
            }
        }

        string IAbstraXDocumentSave.DebugInfo
        {
            get
            {
                return baseObject.DebugInfo;
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public bool IsItemDirty(uint itemid, IUnknown punkDocData)
        {
            throw new NotImplementedException();
        }

        public bool SaveItem(HydraSaveFlags dwSave, string pszSilentSaveAsName, uint itemid, IUnknown punkDocData, out bool pfCanceled)
        {
            throw new NotImplementedException();
        }

        public bool IsItemReloadable(uint itemid)
        {
            throw new NotImplementedException();
        }

        public void ReloadItem(uint itemid)
        {
            throw new NotImplementedException();
        }

        public void IgnoreItemFileChanges(uint itemid, bool fIgnore)
        {
            throw new NotImplementedException();
        }

        public bool IsDirty()
        {
            // TODO - return whether or not is dirty, this will be called every second doc is open and app is idle

            return isDirty;
        }

        public bool Load(IAbstraXDocumentSave pstm)
        {
            loading = true;

            try
            {
                // TODO - do loading here
            }
            finally
            {
                loading = false;
            }

            return true;
        }

        public void Save(IAbstraXDocumentSave pstm, bool fClearDirty)
        {
            // TODO - save here

            throw new NotImplementedException();
        }

        public bool GetClassID(out Guid pClassID)
        {
            throw new NotImplementedException();
        }

        public bool IsDisposed
        {
            get { throw new NotImplementedException(); }
        }

        public virtual bool QueryInterface(Guid iid, out IUnknown interfaceObject)
        {
            var isInterface = this.GetType().GetInterfaces().Any(i =>
            {
                return i.GUID == iid || i.GetCustomAttributes(true).OfType<GuidAttribute>().Any(a =>
                {
                    return a == iid;
                });
            });

            if (isInterface)
            {
                interfaceObject = this;
                return true;
            }
            else if (false)
            {
            }
            else
            {
                interfaceObject = new CommonException(HydraConstants.E_NOINTERFACE);
                return false;
            }
        }

        public virtual bool QueryInterface<T>(out T interfaceObject)
        {
            bool isInterface = false;

            if (typeof(T).HasGuid())
            {
                var iid = typeof(T).GetGuid();
                
                isInterface = this.GetType().GetInterfaces().Any(i =>
                {
                    return i.GUID == iid || i.GetCustomAttributes(true).OfType<GuidAttribute>().Any(a =>
                    {
                        return a == iid;
                    });
                });
            }

            if (isInterface)
            {
                interfaceObject = (T)(object)this;
                return true;
            }
            else if (this is T)
            {
                interfaceObject = (T)(object)this;
                return true;
            }
            else
            {
                interfaceObject = (T)(object)new CommonException(HydraConstants.E_NOINTERFACE);
                return false;
            }
        }

        public void AddView(IDocumentView view)
        {
            views.Add(view);
        }

        public void CloseView(IDocumentView view)
        {
            views.Remove(view);
        }

        public void CloseAllViews()
        {
            views.Clear();
        }

        public void UpdateAllViews()
        {
            views.ForEach(v => v.UpdateData());
        }

        public bool GetGuidEditorType(out Guid pClassID)
        {
            throw new NotImplementedException();
        }

        public bool IsDocDataDirty(out bool pfDirty)
        {
            pfDirty = isDirty? false : true;

            return true;

        }

        public bool SetUntitledDocPath(string pszDocDataPath)
        {
            throw new NotImplementedException();
        }

        public bool LoadDocData(string pszMkDocument)
        {
            return ((IPersistObject<IAbstraXDocumentSave>)this).Load(this);
        }

        public bool SaveDocData(HydraSaveFlags dwSave, out string pbstrMkDocumentNew, out bool pfSaveCanceled)
        {
            throw new NotImplementedException();
        }

        public bool Close()
        {
            throw new NotImplementedException();
        }

        public bool OnRegisterDocData(uint docCookie, IHydraHierarchy pHierNew, uint itemidNew)
        {
            this.docCookie = docCookie;
            return true;
        }

        public bool RenameDocData(HydraRunningDocumentTableAttributes grfAttribs, IHydraHierarchy pHierNew, uint itemidNew, string pszMkDocumentNew)
        {
            throw new NotImplementedException();
        }

        public bool IsDocDataReloadable(out bool pfReloadable)
        {
            throw new NotImplementedException();
        }

        public bool ReloadDocData(HydraReloadDocData grfFlags)
        {
            throw new NotImplementedException();
        }

        public bool SetDocDataDirty(int fDirty)
        {
            throw new NotImplementedException();
        }

        public bool IsDocDataReadOnly(out int pfReadOnly)
        {
            throw new NotImplementedException();
        }

        public bool SetDocDataReadOnly(int fReadOnly)
        {
            throw new NotImplementedException();
        }

        bool IPersistObject<IAbstraXDocumentSave>.IsDirty
        {
            get 
            { 
                throw new NotImplementedException(); 
            }
        }

        bool IPersistObject<IAbstraXDocumentSave>.Save(IAbstraXDocumentSave pstm, bool fClearDirty)
        {
            throw new NotImplementedException();
        }

        public void SetSite(IUnknown pUnkSite)
        {
            pUnkSite.QueryInterface<IQueryServiceProvider>(out serviceProvider);
        }

        public bool GetSite(Guid riid, out IUnknown ppvSite)
        {
            ppvSite = serviceProvider;
            return true;
        }

        public bool GetSite<T>(Guid riid, out T ppvSite)
        {
            ppvSite = (T) serviceProvider;
            return true;
        }

        public EnumInvokeOperation<CommittedState> GetCommittedState()
        {
            // TODO (PHASE 2) - make a call to the database to determine whether or not committed

            var invokeOperation = new EnumInvokeOperation<CommittedState>();
            CommittedState commitedState = CommittedState.NotSet;

            if (baseObject.HasDocumentation)
            {
                EnumUtil.SetFlag<CommittedState>(commitedState, CommittedState.HasDocumentation);
            }
            else
            {
                EnumUtil.RemoveFlag<CommittedState>(commitedState, CommittedState.HasDocumentation);
            }

            invokeOperation.DelaySetCompleted(commitedState);

            return invokeOperation;
        }
    }
}
#endif


